<?php
// +----------------------------------------------------------------------
// | yogurt
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Author: fengyi <1719847255.qq.com>
// +----------------------------------------------------------------------
namespace yogurt;
/**
 * Class Route
 * @package yogurt
 * @method \yogurt\Route get(string $url, mixed $callback) static get路由
 * @method \yogurt\Route post(string $url, mixed $callback) static post路由
 * @method \yogurt\Route any(string $url, mixed $callback) static get|post路由
 */
class Route
{
    /**
     * @var array
     */
    protected static $routes = [];

    /**
     * 路由初始化方法
     * @return void
     * @throws \yogurt\Exception|\ReflectionException
     */
    public static function init()
    {
        self::dispatch(Request::url(false));
    }


    /**
     * 检测路由
     * @return bool
     * @throws \yogurt\Exception|\ReflectionException
     */
    public static function checkRoute(): bool
    {
        $flag = false;
        self::getRouteFiles();
        $urls = array_column(self::$routes, 'url');
        if (self::matchRoute($urls, Request::url(false))) {
            $flag = true;
        }
        if ($flag) {
            self::init();
        }
        return $flag;
    }

    /**
     * 获取所有路由文件
     * @throws \yogurt\Exception
     */
    public static function getRouteFiles()
    {
        $dir = ROOT_PATH . Config::get('route.route_dir');
        $files = scandir($dir);
        foreach ($files as $file) {
            if ($file != '.' && $file != '..') {
                Builder::includeFile($dir . '/' . $file);
            }
        }
    }

    /**
     * 检测请求方式
     * @param $method
     */
    public static function checkMethod($method)
    {
        if (strtolower(Request::method()) != $method && $method != 'any') {
            exit('405 Not Allowed');
        }
    }

    /**
     * 路由入口
     * @param $method
     * @param $args
     */
    public static function __callStatic($method, $args)
    {
        $routeArr = [];
        $routeArr['method'] = $method;
        $routeArr['url'] = $args[0];
        $routeArr['callback'] = $args[1];
        array_push(self::$routes, $routeArr);
    }

    /**
     * 执行闭包
     * @param $currentPath
     * @return void
     * @throws \yogurt\Exception|\ReflectionException
     */
    public static function dispatch($currentPath)
    {
        foreach (self::$routes as $route) {
            if (!self::matchRoute($route['url'], $currentPath)) {
                continue;
            }
            // 检测请求方法是否一致
            self::checkMethod($route['method']);
            // 回调函数直接执行
            if (is_object($route['callback'])) {
                echo $route['callback']();
                break;
            }
            // 执行控制器前置方法
            Builder::beforeExecController($route['callback']);
            break;
        }
    }

    /**
     * 匹配路由，目前只是判断相等，后期可通过正则模糊匹配
     * @param $url
     * @param $currentPath
     * @return bool
     */
    public static function matchRoute($url, $currentPath): bool
    {
        if (is_string($url)) {
            if (strpos($currentPath, $url) === false) {
                return false;
            }
            $surplus = str_replace($url, '', $currentPath);
            if (strpos($surplus, '/') === false) {
                return true;
            }
        }
        if (is_array($url)) {
            if (in_array($currentPath, $url)) {
                return true;
            }
            foreach ($url as $value) {
                if (strpos($currentPath, $value) === false) {
                    continue;
                }
                $surplus = str_replace($value, '', $currentPath);
                if (strpos($surplus, '/') === false) {
                    return true;
                }
            }
        }
        return false;
    }

}
